#ifndef __INKLUDE_C_TCP_CLIENT_H__
#define __INKLUDE_C_TCP_CLIENT_H__

#include <Inklude/Inklude.h>
#include <Inklude/ikINetClient.h>
#include <memory>

namespace Inklude
{
    namespace Internal
    {
        class ikCTcpBoost;
    }

    enum INKLUDE_TCP
    {
        IK_TCP_NON_BLOCKING = 0,
        IK_TCP_BLOCKING = 1
    };

    class ikCTcpServer;

    class INKLUDE_CLASS_EXPORT ikCTcpClient
    {
    public:
        typedef std::shared_ptr<std::function<void (size_t)> > AsyncHandler;

        ikCTcpClient();
        ikCTcpClient(std::shared_ptr<Inklude::Internal::ikCTcpBoost> pBoostTcp);
        ~ikCTcpClient() {}
        void SetDestinationAddress(const char* IPAddress, unsigned int nPort);
        bool ConnectToServer();
        void AsyncConnectToServer(AsyncHandler endHandler);
        size_t Wrtie(void* pBuffer, size_t nDataSize);
        size_t Read(void* pBuffer, size_t nDataSize);

        void AsyncWrite(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);
        void AsyncRead(void* pBuffer, size_t nDataSize, AsyncHandler endHandler);
        bool IsConnected();

        void _internal_set_con_setting(int password);

    protected:
        void _init();

    private:
        int m_nPort;
        bool m_bConnected;
        std::shared_ptr<Inklude::Internal::ikCTcpBoost> m_pTcp;
    };

    typedef std::shared_ptr<ikCTcpClient> ikCTcpClientPtr;

    class INKLUDE_CLASS_EXPORT ikCTcpClientASync : public ikINetClient
    {
    public:
        ikCTcpClientASync() : m_pTcp(new ikCTcpClient) {m_pServer = NULL;}
        virtual ~ikCTcpClientASync();
        virtual void Initialize(unsigned int nRecvPort = 0);
        virtual void SetDestinationAddress(const char* IPAddress, size_t nPort);
        virtual size_t Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual size_t Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual void Close();


    private:
        std::shared_ptr<Inklude::ikCTcpClient> m_pTcp;
        std::shared_ptr<ikCTcpServer> m_pServer;
    };

    class INKLUDE_CLASS_EXPORT ikCTcpClientSync : public ikINetClient
    {
    public:
        ikCTcpClientSync() : m_pTcp(new ikCTcpClient) {m_pServer = NULL;}
        virtual ~ikCTcpClientSync();
        virtual void Initialize(unsigned int nRecvPort = 0);
        virtual void SetDestinationAddress(const char* IPAddress, unsigned int nPort);
        virtual size_t Send(const void* pBuffer, size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual size_t Receive(void* pBuffer, const size_t nDataSize, AsyncHandler endHandler = NULL);
        virtual void Close();

    private:
        std::shared_ptr<Inklude::ikCTcpClient> m_pTcp;
        std::shared_ptr<ikCTcpServer> m_pServer;
    };
}

#endif // __INKLUDE_C_TCP_CLIENT_H__

